//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "pseudo.h"
#include "clsinfo.h"
#include "systype.h"
#include "prxstub.h"
#include "marshal.h"
#include "pcentral.h"
#include "sharecls.h"
#include "namedobj.h"
#include "namedmutex.h"
#include "namedevent.h"
#include "sharedmem.h"
#include "namedcondition.h"
#include <aura.h>

extern void UnicToAnsi(char *pszName, const wchar_t *pwszName);

CARAPI CPseudoSyscall::SysPrint(
    /* [in]  */ const wchar_t * wstr)
{
    char *str = (char*)_alloca(wcslen(wstr) + 1);
    UnicToAnsi(str, wstr);
    Aura_printf("%s", str);
    return NOERROR;
}

CARAPI CPseudoSyscall::SysErrorPrint(
    /* [in]  */ const wchar_t * wstr)
{
    AuraSystem_ErrorPrint((Aura_PWChar)wstr);
    return NOERROR;
}

CARAPI CPseudoSyscall::SysGetVirtualCode(
    /* [in]  */ struct KBDStatus * pVirtualCode)
{
    return E_NOT_IMPLEMENTED;
}

CARAPI CPseudoSyscall::SysSetBreakPoint(
    /* [in]  */ UInt32 uNo,
    /* [in]  */ BreakPointType type,
    /* [in]  */ PVoid pvAddress,
    /* [in]  */ UInt32 uLength)
{
    return E_NOT_IMPLEMENTED;
}

CARAPI CPseudoSyscall::SysRegisterClassInfo(
    /* [in]  */ CIClassInfo * pClassInfo)
{
    if (NULL == pClassInfo) {
        return E_INVALID_ARGUMENT;
    }

    return RegisterSharedClassInfo(pClassInfo);
}

CARAPI CPseudoSyscall::SysReply(
    /* [in]  */ ECode channelId,
    /* [in]  */ PVoid pvOutBuf,
    /* [in]  */ size_t uOutBufSize)
{
    return (ECode)AuraIpcChannel_AsyncWrite((Aura_ChannelId)channelId, pvOutBuf, (Aura_UInt32)uOutBufSize);
}

extern PVoid g_marshalLock;
extern WStringBuf_<32> s_processServiceName;
extern IStub *s_pCurrentprocessStub;

CARAPI CPseudoSyscall::RegisterRunningObject(
    /* [in]  */ WString srvName,
    /* [in]  */ PInterface pService)
{
    ECode ec = NOERROR;
    IProxy * pIProxy = NULL;

    if (srvName.IsNullOrEmpty() || (NULL == pService)) {
        return E_INVALID_ARGUMENT;
    }

    if (srvName.GetLength(MAXIMUM_SERVICE_NAME_LENGTH) < 0) {
        return E_SERVICE_NAME_TOO_LONG;
    }

    pIProxy = (IProxy*)pService->Probe(EIID_IProxy);
    if (pIProxy) {
        oid_t oid;
        ec = pIProxy->GetOid(&oid);
        if (SUCCEEDED(ec)) {
            ec = CPseudoCentral::SrvcRegisterService(srvName, oid);
        }
    }
    else {
        IStub  * pIStub = NULL;
        AuraCriticalSection_Enter(g_marshalLock);
        ec =  CObjectStub::S_CreateObject(srvName, pService, &pIStub);
        AuraCriticalSection_Leave(g_marshalLock);

        if (!wcscmp((const wchar_t *)s_processServiceName,
                    (const wchar_t *)srvName)) {
            s_pCurrentprocessStub = pIStub;
        }
       // pIStub->Release();
    }

    return ec;
}

CARAPI CPseudoSyscall::FindRunningObject(
    /* [in]  */ WString srvName,
    /* [in]  */ PInterface * ppService)
{
    InterfacePack iPack;
    ObjectType type;
    ECode ec = NULL;
    NamedObjectFactory * pFactory = NULL;

    if (srvName.IsNullOrEmpty() || (NULL == ppService)) {
        return E_INVALID_ARGUMENT;
    }

    iPack.m_pClsEntry = 0;

    ec = CPseudoCentral::SrvcResolveCommon(srvName,
                                         &iPack.m_pid,
                                         &type,
                                         &iPack.m_oid,
                                         &iPack.m_clsid,
                                         &iPack.m_uIndex);
    if (FAILED(ec)) {
        return ec;
    }
    iPack.m_pid = AURA_INVALID_PID;
    switch (type) {
    case ObjectType_MetaData:
        return StdUnmarshalInterface(&iPack, NULL, TRUE, ppService);

    case ObjectType_NamedMutex:
        pFactory = new CNamedMutexFactory(srvName);
        break;
    case ObjectType_NamedEvent:
        pFactory = new CNamedEventFactory(srvName);
        break;
    case ObjectType_NamedCondition:
        pFactory = new CNamedConditionFactory(srvName);
        break;
    case ObjectType_NamedRwLock:
        return E_NOT_IMPLEMENTED;

    case ObjectType_SharedMemory:
        pFactory = new CSharedMemoryFactory(srvName);
        break;
    default:
        assert(0);
    }

    if (NULL == pFactory) {
        return E_OUT_OF_MEMORY;
    }

    NamedObject * pNamedObj = NULL;
    ec = NamedObject::S_ResolveObject(pFactory, iPack.m_oid, &pNamedObj);
    if (FAILED(ec)) {
        delete pFactory;
        return ec;
    }
    *ppService = pNamedObj->GetObject();
    delete pFactory;

    return ec;
}

CARAPI CPseudoSyscall::WaitForRunningObject(
    /* [in]  */ WString srvName,
    /* [in]  */ Int32 timeout,
    /* [out] */ WaitResult *pResult)
{
    if (srvName.IsNullOrEmpty() || NULL == pResult) {
        return E_INVALID_ARGUMENT;
    }

    return CPseudoCentral::SrvcWaitService(srvName, timeout, pResult);
}

CARAPI CPseudoSyscall::UnregisterRunningObject(
    /* [in]  */ WString srvName)
{
    if (srvName.IsNullOrEmpty()) {
        return E_INVALID_ARGUMENT;
    }

    return CPseudoCentral::SrvcUnregsiterCommon(srvName);
}
